\documentclass[UTF-8, 12pt]{ctexart}
\setmainfont{Ubuntu}
\setCJKmainfont{STXihei}
\usepackage{fancyhdr}
\title{第二周实验报告}
\author{沈家成}
\date{\today}
\pagestyle{fancy}
\lhead{第二周}
\chead{}
\rhead{\today}
\lfoot{}
\cfoot{\thepage}
\rfoot{}
\renewcommand{\headrulewidth}{0.4pt}
\renewcommand{\headwidth}{\textwidth}
\renewcommand{\footrulewidth}{0pt}

\begin{document}
\maketitle
\section{1010 二哥的储蓄计划}
    \subsection{问题分析}
    \paragraph{}
    复杂之处主要在于钱的进进出出比较频繁，容易分不清。多用一些变量表示，分清逻辑层次就可以了。
    \subsection{代码实现}
    \paragraph{}
    定义了一个 money cost 数组，储存每月的花费。定义了 money hand, money receive, money store 分别表示二哥手里的钱，每月领到的零花钱，存到妈妈那里的钱。
    \paragraph{}
    然后设置一个 12 次的循环，表示每个月的过程。先是从妈妈那里领到 300 元零花钱，然后扣除掉这个月的花费，如果小于零，表示这个月要省吃俭用，输出月份，退出程序；如果大于等于 100，就进入一个 while 循环，每次存 100 元，直到月末手里的钱不足 100 元。
    \subsection{小结}
    \paragraph{}
    取好变量的名字，表达清楚逻辑关系，编写代码就会更有思路。

\section{1202 bigint}
    \subsection{问题分析}
    \paragraph{}
    最高1000000位的加法，是没有内置的整形可以处理的，需要自己设计一个数据结构（要求的是链表）并实现加法。
    \subsection{代码实现}
        \subsubsection{读取数据}
        \paragraph{}
    因为要用链表单个单个地储存数字，所以不能直接用 cin 的流处理，而是改用更基础的 cin.get()，通过条件循环，以读到换行符作为终止标志。分两次读取两个大整数。为了便于加法的实现，后读取到的数字会插入到头结点后面。
        \subsubsection{加法}
        \paragraph{}
    加法从后往前，按位相加。进位的问题借鉴了数字电路里的加法器，通过设置 Carry 位表示进位与否，再在下一位的加法里考虑进去。为了适应两个整数长短不同和最高位进位的情况，循环终止的条件设置为第一个整数到了最高位、并且第二个整数到了最高位、并且 Carry 位已经清零。
    \subsection{小结}
    因为单链表从头到尾比较方便，储存读取数据的时候，要根据前后顺序设计，便于提高效率。

\section{1203 link}
    \subsection{问题分析}
    \paragraph{}
    要求用运算符重载来连接两个线性表，涉及到类的许多运算符重载的函数。同时由于使用到了动态数组，就需要管理内存，防止内存泄露和重复释放。
    \subsection{代码实现}
    \paragraph{}
    为了适应int，char，double三种数据类型，需要用到模板类。使用模板类时要注意，在函数实现之前声明这是模板类的函数，否则编译失败。
    \paragraph{}
    类里需要重载加法和赋值运算符来实现简便的连接操作，重载函数作为成员函数时，二元运算符只有一个参数，另一个参与运算的对象是 this。同时还需要重载拷贝构造函数来防止动态数组被多次释放，造成 double free 错误。
    \subsection{小结}
    \paragraph{}
    动态数组的使用要仔细管理内存，防止重复释放内存。重载运算符能方便类的使用，但也对类的设计提出了更高的要求。
    
\section{1203 edit}
    \subsection{问题分析}
    \paragraph{}
    题目要求设计一个简单的文本编辑器，有显示，插入，修改功能。可以将其封装成一个类，用成员函数实现各个功能，再用一个函数判断执行哪项功能。退出功能比较特殊，可以设置一个单独的变量表示当前状态，进入退出的函数时，设为退出状态，主函数根据当前状态决定是否退出程序。
    \subsection{代码实现}
        \subsubsection{文本储存}
        \paragraph{}
        考虑到文本的频繁删减操作，没有选择用动态数组，否则频繁地申请释放内存容易造成碎片，而且容易造成内存泄露，因此选择用一个 101*2001 的数组储存，多余的字符用来标记换行符和文件结束标识符。
        \subsubsection{状态切换}
        \paragraph{}
        设置了一个枚举类型的变量，有两个值：INIT 和 QUIT，表示初始化完和退出两种状态。对象构造时会设置状态为初始化完，进入 quit() 函数时会设置状态为退出。在主函数中，每次获取命令前都要判断当前状态是否为退出状态，如果是，就退出循环，继而退出程序。
        \subsubsection{插入操作}
        \paragraph{}
        判断是插入操作后，就会读取插入行、插入列、插入数据三个参数。首先判断参数是否合法，如果不合法，输出 Error 并直接退出函数。如果合法的话，先把插入列之后的数据后移，给插入的数据留出空间，再把要插入的数据复制到预留的空间上，这样就完成了插入操作。
        \subsubsection{删除操作}
        \paragraph{}
        进入删除操作的函数后，会读取删除行、删除列、删除个数三个参数。首先还是判断参数是否合法。如果合法，将删除后剩余的文本移到删除的地方，无需先将需要删除的文本置零，就可以实现删除的操作了。
    \subsection{小结}
    \paragraph{}
    这是一个比较复杂的系统，需要各个部件都正常工作，整个系统才能正常工作。惭愧的是，我提交了十几次，最后还是只有一半的答案是正确的。重新测试了自己的程序 5 天，试过了各种我能想到的情况，但不知道还有什么情况是没想到的。怎么编写程序是一门技术，怎么测试程序也是一门技术。
\end{document}
